/*******************************************************************************
 * Copyright (c) 2009 Kevin Bierhoff and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Kevin Bierhoff - initial API and implementation
 *******************************************************************************/
package com.googlecode.twelfdevtools.editor;

import org.eclipse.debug.ui.console.FileLink;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetectorExtension;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.texteditor.ITextEditor;

import com.googlecode.twelfdevtools.model.IElfFile;
import com.googlecode.twelfdevtools.model.ITwelfNamedElement;
import com.googlecode.twelfdevtools.model.TwelfModel;

/**
 * @author kevin
 *
 */
public class TwelfHyperlinkDetector extends AbstractHyperlinkDetector implements
		IHyperlinkDetector, IHyperlinkDetectorExtension {

	public IHyperlink[] detectHyperlinks(final ITextViewer textViewer,
			IRegion region, boolean canShowMultipleHyperlinks) {
		IElfFile file = TwelfEditor.getEditedFile((ITextEditor) getAdapter(ITextEditor.class));
		
		if(textViewer instanceof ISourceViewer) {
			ISourceViewer sourceViewer = (ISourceViewer) textViewer;
			IDocument doc = sourceViewer.getDocument();
			final IRegion sourceRegion = TwelfModel.getModel().findTwelfWord(doc, region.getOffset());
			try {
				final ITwelfNamedElement c = TwelfModel.getModel().getBinding(file, doc, sourceRegion);
				if (c == null)
					// no binding -> quit
					return null;
				final IRegion target = c.getIdentifierRange(doc);
				if(contains(target, sourceRegion))
					// looking at the target of the link we could create
					return null;
				return new IHyperlink[] { 
					new TwelfDeclarationHyperlink(target, c, sourceRegion) };
			}
			catch(BadLocationException e) {
				// TODO 
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private static boolean contains(IRegion containing, IRegion contained) {
		int dist = containing.getOffset() - contained.getOffset();
		int endDist = dist + contained.getLength();
		return (dist >= 0 && endDist <= containing.getLength());
	}

	private static final class TwelfDeclarationHyperlink implements IHyperlink {
		private final IRegion target;
		private final ITwelfNamedElement decl;
		private final IRegion sourceRegion;

		private TwelfDeclarationHyperlink(IRegion target, ITwelfNamedElement decl,
				IRegion sourceRegion) {
			this.target = target;
			this.decl = decl;
			this.sourceRegion = sourceRegion;
		}

		public IRegion getHyperlinkRegion() {
			return sourceRegion;
		}

		public String getHyperlinkText() {
			return decl.getId();
		}

		public String getTypeLabel() {
			return "twelfIdentifier";
		}

		public void open() {
			FileLink link = new FileLink(decl.getFile().getResource(), 
					null, target.getOffset(), target.getLength(), 
					1 /* FileLink only works with positive line number */);
			link.linkActivated();
//			textViewer.setSelectedRange(target.getOffset(), target.getLength());
//			textViewer.revealRange(target.getOffset(), target.getLength());
		}
	}
}
